#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <linux/if.h>

#define		BUFLEN		42

int main(int argc, char **argv)
{
    int skfd, n;
    char buf[BUFLEN] = {0};
    struct ether_header	*eth;
    struct ether_arp *arp;
    struct sockaddr_ll toaddr;
    struct in_addr targetIP, srcIP;
    struct ifreq ifr;

    unsigned char src_mac[ETH_ALEN] = {0};
    unsigned char dst_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    
    if (3 != argc){
	printf("Usuage: %s netdevName dstIP\n", argv[0]);
	exit(1);
    }

    if (0 > (skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)))){
	perror("Create Error");
	exit(1);
    }

    bzero(&toaddr, sizeof(toaddr));
    bzero(&ifr, sizeof(ifr));
    strcpy(ifr.ifr_name, argv[1]);

    if (-1 == ioctl(skfd, SIOCGIFINDEX, &ifr)){
	perror("Get dev index error\n");
	exit(1);
    }

    toaddr.sll_ifindex = ifr.ifr_ifindex;
    if (-1 == ioctl(skfd, SIOCGIFADDR, &ifr)){
	perror("Get IP addr error\n");
	exit(1);
    }

    srcIP.s_addr = ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr;

    if (-1 == ioctl(skfd, SIOCGIFHWADDR, &ifr)){
	perror("Get dev addr error\n");
	exit(1);
    }

    memcpy(src_mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    eth = (struct ether_header *)buf;
    memcpy(eth->ether_dhost, dst_mac, ETH_ALEN);
    memcpy(eth->ether_shost, src_mac, ETH_ALEN);
    eth->ether_type = htons(ETHERTYPE_ARP);

    arp = (struct arphdr *)(buf + sizeof(struct ether_header));
    arp->arp_hrd = htons(ARPHRD_ETHER);
    arp->arp_pro = htons(ETHERTYPE_IP);
    arp->arp_hln = ETH_ALEN;
    arp->arp_pln = 4;
    arp->arp_op = htons(ARPOP_REQUEST);
    memcpy(arp->arp_sha, src_mac, ETH_ALEN);
    memcpy(arp->arp_spa, &srcIP, 4);
    inet_pton(AF_INET, argv[2], &targetIP);
    memcpy(arp->arp_tpa, &targetIP, 4);

    n = sendto(skfd, buf, BUFLEN, 0, (struct sockaddr *)&toaddr, sizeof(toaddr));

    close(skfd);
    return 0;
}
	    

